/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#include "stdafx.h"
#include "CScriptableDeviceCapability.h"
#include "scripting.h"


CScriptableDeviceCapability::CScriptableDeviceCapability()
    : m_cap( NULL ),
    m_itemJsArray( NULL ),
    m_scriptableControl( NULL )
{
}

CScriptableDeviceCapability::~CScriptableDeviceCapability()
{
}

void CScriptableDeviceCapability::setData( BaseCap* cap )
{
    m_cap = cap;
}

#define SET_VARIANT_VALUE_NUMERIC( type, field )\
    if ( m_cap->valueType == CapValueType::Int )\
{\
    pVal->vt = VT_I4;\
    pVal->intVal = ( ( Int##type##Cap* ) m_cap )->field;\
}\
    else if ( m_cap->valueType == CapValueType::Float )\
{\
    pVal->vt = VT_R4;\
    pVal->fltVal = ( ( Float##type##Cap* ) m_cap )->field;\
}

#define SET_VARIANT_VALUE( type, field )\
    SET_VARIANT_VALUE_NUMERIC( type, field )\
    else if ( m_cap->valueType == CapValueType::Bool )\
{\
    pVal->vt = VT_BOOL;\
    pVal->boolVal = ( ( Bool##type##Cap* ) m_cap )->field;\
}


STDMETHODIMP CScriptableDeviceCapability::get_cap( VARIANT* pVal )
{
    pVal->vt = VT_UI4;
    pVal->uintVal = m_cap->cap;

    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_type( VARIANT* pVal )
{
    pVal->vt = VT_UI4;
    pVal->uintVal = ( UINT ) m_cap->type;

    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_valueType( VARIANT* pVal )
{
    pVal->vt = VT_UI4;
    pVal->uintVal = ( UINT ) m_cap->valueType;

    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_item( VARIANT* pVal )
{
    if ( m_cap->type == CapType::OneValue )
    {
        SET_VARIANT_VALUE( Value, item );
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_count( VARIANT* pVal )
{
    if ( m_cap->type == CapType::List )
    {
        pVal->vt = VT_UI4;
        pVal->uintVal = ( ( ListBaseCap* ) m_cap )->count;
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_items( VARIANT* pVal )
{
    if ( m_cap->type == CapType::List )
    {
        if ( !m_itemJsArray )
        {
            HRESULT hr = ::newArray( JsArray, m_scriptableControl->m_browser, &m_itemJsArray );

            ListBaseCap* listBaseCap = ( ListBaseCap* ) m_cap;
            size_t count = listBaseCap->count;

            for ( size_t i = 0; i < count; i++ )
            {
                VARIANT v1 = { 0 };

                switch ( m_cap->valueType )
                {
                case CapValueType::Int:
                    v1.vt = VT_I4;
                    v1.intVal = ( ( IntListCap* ) listBaseCap )->items[ i ];
                    break;

                case CapValueType::Float:
                    v1.vt = VT_R8;
                    v1.dblVal = ( double ) ( ( FloatListCap* ) listBaseCap )->items[ i ];
                    break;
                }

                if ( ::pushArray( m_itemJsArray, v1 ) != S_OK )
                {
                    m_itemJsArray->Release();
                    m_itemJsArray = NULL;
                    break;
                }
            }
        }

        if ( m_itemJsArray )
        {
            m_itemJsArray->AddRef();

            pVal->vt = VT_DISPATCH;
            pVal->pdispVal = m_itemJsArray;
        }
    }

    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_defaultIndex( VARIANT* pVal )
{
    if ( m_cap->type == CapType::List )
    {
        pVal->vt = VT_I4;
        pVal->intVal = ( ( ListBaseCap* ) m_cap )->defaultIndex;
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_currentIndex( VARIANT* pVal )
{
    if ( m_cap->type == CapType::List )
    {
        pVal->vt = VT_I4;
        pVal->intVal = ( ( ListBaseCap* ) m_cap )->currentIndex;
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_min( VARIANT* pVal )
{
    if ( m_cap->type == CapType::Range )
    {
        SET_VARIANT_VALUE_NUMERIC( Range, minValue );
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_max( VARIANT* pVal )
{
    if ( m_cap->type == CapType::Range )
    {
        SET_VARIANT_VALUE_NUMERIC( Range, maxValue );
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_step( VARIANT* pVal )
{
    if ( m_cap->type == CapType::Range )
    {
        SET_VARIANT_VALUE_NUMERIC( Range, stepValue );
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_defaultValue( VARIANT* pVal )
{
    if ( m_cap->type == CapType::Range )
    {
        SET_VARIANT_VALUE_NUMERIC( Range, defaultValue );
    }
    return S_OK;
}

STDMETHODIMP CScriptableDeviceCapability::get_currentValue( VARIANT* pVal )
{
    if ( m_cap->type == CapType::Range )
    {
        SET_VARIANT_VALUE_NUMERIC( Range, currentValue );
    }
    return S_OK;
}
